package com.rizzo.analytics.domain.performance;

import com.google.common.base.Splitter;
import com.google.common.collect.Sets;
import com.rizzo.infrastructure.web.validator.Save;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.joda.time.DateTime;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import java.io.Serializable;
import java.util.Comparator;
import java.util.Set;

public class CallInfo implements Serializable, Comparable<CallInfo> {

	private static final long serialVersionUID = 6L;

	public enum CallSort {
		BY_TIME, BY_DURATION;
		public static final String allowableValues = "BY_TIME,BY_DURATION";
	}

	@NotNull(groups = {Save.class}, message = "performance.monitored.service.call.time.field.empty")
	@Past(groups = {Save.class}, message = "performance.monitored.service.call.time.future")
	private DateTime time;

	private int duration;

	public CallInfo() {
	}

	public CallInfo(DateTime time, int duration) {
		this.time = time;
		this.duration = duration;
	}

	public DateTime getTime() {
		return time;
	}

	public void setTime(DateTime time) {
		this.time = time;
	}

	public Integer getDuration() {
		return duration;
	}

	public void setDuration(int duration) {
		this.duration = duration;
	}

	public static Comparator<CallInfo> getComparator(CallSort callSort) {
		switch (callSort) {
			case BY_DURATION:
				return new CallInfoDurationComparator();
			case BY_TIME:
				return new CallInfoTimeComparator();
			default:
				return null;
		}
	}

	// TODO test this method to the bone
	public static Set<CallInfo> parseRange(String range, CallSort callSort) {
		Set<CallInfo> callInfos = Sets.newTreeSet(getComparator(callSort));
		for (String dataPoint : Splitter.fixedLength(19).split(range)) {
			if (StringUtils.isNotBlank(dataPoint) && dataPoint.length() == 19) {
				callInfos.add(new CallInfo(
						new DateTime(Long.parseLong(dataPoint.substring(0, 13))), Integer.parseInt(dataPoint.substring(13, 19))));
			} else {
				throw new IllegalArgumentException("CallInfo in appending performance value is not of correct size!");
			}
		}
		return callInfos;
	}

	@Override
	public int compareTo(CallInfo o) {
		return o.getTime().compareTo(this.getTime());
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) {
			return true;
		}
		if (o == null || getClass() != o.getClass()) {
			return false;
		}

		CallInfo callInfo = (CallInfo) o;

		if (Double.compare(callInfo.duration, duration) != 0) {
			return false;
		}
		if (!time.isEqual(callInfo.time)) {
			return false;
		}

		return true;
	}

	@Override
	public int hashCode() {
		return HashCodeBuilder.reflectionHashCode(this);
	}


}
